package org.hzz.coupon.infrastructure.repository.mybatis;

import io.gitee.pkmer.convention.converter.RecordAndEntityConverter;
import io.gitee.pkmer.convention.page.PageResponse;
import io.gitee.pkmer.convention.page.query.PageQuery;
import io.gitee.pkmer.convention.repository.nomapper.PageBaseRepository;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.hzz.coupon.infrastructure.dao.mapper.user.coupon.UserCouponDynamicMapper;
import org.hzz.coupon.infrastructure.dao.mapper.user.coupon.UserCouponExtMapper;
import org.hzz.coupon.infrastructure.dao.mapper.user.coupon.UserCouponMapper;
import org.hzz.coupon.infrastructure.dao.model.user.coupon.UserCoupon;
import org.hzz.promotions.domain.entity.UserCouponEntity;
import org.hzz.promotions.domain.repository.UserCouponRepository;
import org.hzz.promotions.domain.valueobject.CouponReceive;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.util.mybatis3.CommonSelectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static org.hzz.coupon.infrastructure.dao.mapper.user.coupon.UserCouponDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.*;

/**
 * @author <a href="mailto:1193094618@qq.com">pkmer</a>
 * <br>
 * <a href = "https://gitee.com/developeros/videos-online">Code Repository</a>
 * At 2024/9/2
 */
@Repository
@Slf4j
public class UserCouponRepositoryImpl
        extends PageBaseRepository<UserCouponExtMapper,UserCoupon>
        implements UserCouponRepository{

    @Setter(onMethod_ = @Autowired)
    private UserCouponMapper mapper;
    @Setter(onMethod_ = @Autowired)
    private UserCouponDynamicMapper dynamicMapper;

    /**
     * {@inheritDoc}
     * @param _userId 用户id
     */
    @Override
    public List<UserCouponEntity> selectUserCouponByUserId(Long _userId) {

        SelectStatementProvider selectStatementProvider = select(userCoupon.allColumns()).from(userCoupon)
                .where(userId, isEqualTo(_userId))
                .build()
                .render(RenderingStrategies.MYBATIS3);

        log.info(selectStatementProvider.getSelectStatement());

        List<UserCoupon> records = dynamicMapper.selectMany(selectStatementProvider);
        return Converter.INSTANCE.toEntities(records);
    }

    /**
     * {@inheritDoc}
     * @param _userId 用户id
     * @param couponIds 优惠券id
     * @return 领取的数量
     */
    @Override
    public List<CouponReceive> countReceivedCouponNum(Long _userId, List<Long> couponIds) {

        /**
         * SELECT
         *     coupon_id,
         *     COUNT(*) AS count
         * FROM
         *     user_coupon
         * WHERE
         *     user_id = :userId
         *     AND coupon_id IN (:list)
         * GROUP BY
         *     coupon_id;
         */

        SelectStatementProvider selectStatementProvider = select(couponId.as("couponId"),count().as("count"))
                .from(userCoupon)
                .where(userId, isEqualTo(_userId))
                .and(couponId, isIn(couponIds))
                .groupBy(couponId)
                .build()
                .render(RenderingStrategies.MYBATIS3);

        log.info(selectStatementProvider.getSelectStatement());

        List<Map<String, Object>> records = dynamicMapper.selectManyMappedRows(selectStatementProvider);

        List<CouponReceive> results = new ArrayList<>(records.size());

        for (int i = 0; i < records.size(); i++) {
            CouponReceive couponReceive = new CouponReceive();
            Map<String, Object> r = records.get(i);
            couponReceive.setCouponId((long)r.get("couponId"))
                            .setCount((long)r.get("count"));
            results.add(couponReceive);
        }
        return results;
    }

    /**
     * {@inheritDoc}
     * @param entity 数据
     */
    @Override
    public void insertUserCoupon(UserCouponEntity entity) {
        UserCoupon record = Converter.INSTANCE.toRecord(entity);
        mapper.insertSelective(record);
    }

    @Override
    public PageResponse<UserCouponEntity> pageQueryUserCoupon(PageQuery pageQuery) {
        PageResponse<UserCoupon> pages = pageQuery(pageQuery);
         return  Converter.INSTANCE.convertToEntityPage(pages);
    }

    @Mapper
    interface Converter extends RecordAndEntityConverter<UserCoupon, UserCouponEntity> {
        Converter INSTANCE = Mappers.getMapper(Converter.class);
    }

}
